﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Collections;

namespace MatlabIG
{
    class Object3DMesh : Object3D
    {
        // loaded mesh/FBX file
        Model model3D;
        Matrix world = Matrix.Identity;
        bool DrawShadow = false;
        Hashtable joints = new Hashtable();

        public Matrix WorldMat
        {
            get { return world; }
            set { world = value;}
        }

        public Hashtable Joints 
        {
            get { return joints; } 
        }

        public void Load(string mesh, bool drawShadow)
        {
            model3D = Globals.Content.Load<Model>(mesh);
            DrawShadow = drawShadow;
        }

        public void Draw()
        {
            DrawModel(model3D);
            if (DrawShadow)
            {
                DrawModelShadow(model3D);
            }
        }

        protected void DrawModel(Model m)
        {
            Matrix[] transforms = new Matrix[m.Bones.Count];
            m.CopyAbsoluteBoneTransformsTo(transforms);
            foreach (ModelMesh mesh in m.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = Globals.ViewMat;
                    effect.Projection = Globals.ProjectionMat;

                    // joint support
                    Matrix add = Matrix.Identity;
                    if(joints[mesh.Name] != null )
                    {
                        add = (Matrix)joints[mesh.Name];
                    }
                    effect.World = transforms[mesh.ParentBone.Index] * add * world;
                }
                mesh.Draw();
            }
        }

        public Matrix GetJointMatrix(string name)
        {
            Matrix total = new Matrix();
            Matrix[] transforms = new Matrix[model3D.Bones.Count];
            model3D.CopyAbsoluteBoneTransformsTo(transforms);

            foreach (ModelMesh mesh in model3D.Meshes)
            {
                if (mesh.Name == name)
                {
                    Matrix add = Matrix.Identity;
                    if (joints[mesh.Name] != null)
                    {
                        add = (Matrix)joints[mesh.Name];
                    }

                    total = transforms[mesh.ParentBone.Index] * add * world;
                }
            }

            return total;
        }

        protected void DrawModelShadow(Model m)
        {
            Globals.Graphics.GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead; // disable depth write!
            Matrix[] transforms = new Matrix[m.Bones.Count];
            m.CopyAbsoluteBoneTransformsTo(transforms);
            foreach (ModelMesh mesh in m.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = Globals.ViewMat;
                    effect.Projection = Globals.ProjectionMat;
                    effect.World = transforms[mesh.ParentBone.Index]  * world * Matrix.CreateShadow(new Vector3(0, 0, 1), new Plane(new Vector3(0, 0, 1), 0.01f));
                }
                mesh.Draw();
            }
            Globals.Graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
        }
    }
}
